import { useEffect, useMemo, useRef, useState } from 'react'
import { Graph } from '@antv/x6'
import { Dnd } from '@antv/x6-plugin-dnd'
import styles from './index.module.less'
import { useProcessMiningEngineStore } from '../../store'
import { Collapse } from '@terminus/nusi-slim'

// #region 初始化图形
const ports = {
  groups: {
    top: {
      position: 'top',
      attrs: {
        circle: {
          r: 4,
          magnet: true,
          stroke: '#5F95FF',
          strokeWidth: 1,
          fill: '#fff',
          style: {
            visibility: 'hidden',
          },
        },
      },
    },
    right: {
      position: 'right',
      attrs: {
        circle: {
          r: 4,
          magnet: true,
          stroke: '#5F95FF',
          strokeWidth: 1,
          fill: '#fff',
          style: {
            visibility: 'hidden',
          },
        },
      },
    },
    bottom: {
      position: 'bottom',
      attrs: {
        circle: {
          r: 4,
          magnet: true,
          stroke: '#5F95FF',
          strokeWidth: 1,
          fill: '#fff',
          style: {
            visibility: 'hidden',
          },
        },
      },
    },
    left: {
      position: 'left',
      attrs: {
        circle: {
          r: 4,
          magnet: true,
          stroke: '#5F95FF',
          strokeWidth: 1,
          fill: '#fff',
          style: {
            visibility: 'hidden',
          },
        },
      },
    },
  },
  items: [
    {
      group: 'top',
    },
    {
      group: 'right',
    },
    {
      group: 'bottom',
    },
    {
      group: 'left',
    },
  ],
}


// 注册自定义节点
function registerNodes(nodes: any[]) {
  for (const node of nodes) {
    // 注册节点
    Graph.registerNode(
      node.shape,
      node,
      true,
    )
  }
}

interface NodeItem {
  shape: string
  label: string
  width: number
  height: number
  attrs: any
  ports: any
}

const NodePanel = () => {
  const graph = useProcessMiningEngineStore((state) => state.graph)
  const dndRef = useRef<Dnd | null>(null)

  const [isRegistered, setIsRegistered] = useState<boolean>(false)

  const nodeConfigs: { title: string; nodes: NodeItem[] }[] = useMemo(() => {
    return [
      {
        title: '核心元素',
        nodes: [
          {
            shape: 'custom-rect-start',
            label: '开始',
            width: 66,
            height: 36,
            attrs: {
              body: {
                rx: 20,
                ry: 26,
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              text: {
                fontSize: 12,
                fill: '#262626',
              },
            },
            ports: { ...ports },
          },
          {
            shape: 'custom-rect-end',
            label: '结束',
            width: 66,
            height: 36,
            attrs: {
              body: {
                rx: 20,
                ry: 26,
                strokeWidth: 1,
                stroke: '#5F95FF',
                fill: '#EFF4FF',
              },
              text: {
                fontSize: 12,
                fill: '#262626',
              },
            },
            ports: { ...ports },
          },
          {
            shape: 'custom-rect-task',
            label: '任务',
            width: 66,
            height: 36,
            attrs: {
              body: {
                rx: 8,
                ry: 8,
                strokeWidth: 1,
                stroke: '#FFA500',
                fill: '#EFF4FF',
              },
              text: {
                fontSize: 12,
                fill: '#262626',
              },
            },
            ports: { ...ports },
          },
        ]
      },
      {
        title: '图表元素',
        nodes: [
          {
            shape: 'custom-rect-chart',
            label: '图表',
            width: 66,
            height: 36,
            attrs: {
              body: {
                rx: 8,
                ry: 8,
                strokeWidth: 1,
                stroke: '#FFA500',
                fill: '#EFF4FF',
              },
              text: {
                fontSize: 12,
                fill: '#262626',
              },
            },
            ports: { ...ports },
          },
        ]
      }
    ]
  }, [])

  useEffect(() => {
    if (!graph || isRegistered) return

    // 注册节点
    const nodesToRegister = nodeConfigs.map(group => {
      const { nodes } = group
      return nodes.map(node => {
        return {
          shape: node.shape,
          inherit: 'rect',
          ...node.attrs,
        }
      })
    }).flat()
    registerNodes(nodesToRegister)

    setIsRegistered(true)

    // 创建 Dnd 实例
    const dnd = new Dnd({
      target: graph,
      scaled: false,
    })
    dndRef.current = dnd

    return () => {
      // 清理工作
    }
  }, [nodeConfigs, isRegistered, graph])

  // 处理拖拽开始
  const handleDragStart = (e: React.DragEvent, config: NodeItem) => {
    if (!graph || !dndRef.current) return

    const node = graph.createNode({
      shape: config.shape,
      width: config.width,
      height: config.height,
      label: config.label,
      attrs: config.attrs,
      ports: config.ports,
    })

    // 使用原生事件进行拖拽
    dndRef.current.start(node, e.nativeEvent)
  }

  return (
    <div className={styles.nodePanel}>
      <Collapse accordion defaultActiveKey={['1']} >
        {nodeConfigs.map((group, index) => (
          <Collapse.Panel header={group.title} key={`${index + 1}`}>
            <div className={styles.nodeList}>
              {group.nodes.map((node, index) => (
                <div
                  key={index}
                  className={styles.nodeItem}
                  draggable
                  onDragStart={(e) => handleDragStart(e, node)}
                >
                  <div
                    className={styles.nodePreview}
                    style={{
                      width: node.width,
                      height: node.height,
                      borderRadius: node.attrs?.body?.rx ? `${node.attrs?.body?.rx}px` : '0',
                      border: `${node.attrs?.body?.strokeWidth}px solid ${node.attrs?.body?.stroke}`,
                      backgroundColor: node.attrs?.body?.fill,
                      color: node.attrs?.text?.fill,
                      fontSize: node.attrs?.text?.fontSize,
                      display: 'flex',
                      alignItems: 'center',
                      justifyContent: 'center',
                    }}
                  >
                    {node.label}
                  </div>
                  <div className={styles.nodeLabel}>{node.label}</div>
                </div>
              ))}
            </div>
          </Collapse.Panel>
        ))}
      </Collapse>
    </div>
  )
}

export default NodePanel
